package com.yz.fanrenmianshi.job;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yz.fanrenmianshi.mapper.QuestionCommentMapper;
import com.yz.fanrenmianshi.mapper.QuestionCommentThumbMapper;
import com.yz.fanrenmianshi.model.entity.QuestionComment;
import com.yz.fanrenmianshi.model.entity.QuestionCommentThumb;
import com.yz.fanrenmianshi.service.CommentThumbRedisService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 评论点赞数据同步任务
 * 定时将Redis中的点赞数据同步到MySQL
 */
@Component
@Slf4j
public class CommentThumbSyncJob {

    @Resource
    private CommentThumbRedisService commentThumbRedisService;

    @Resource
    private QuestionCommentThumbMapper questionCommentThumbMapper;

    @Resource
    private QuestionCommentMapper questionCommentMapper;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private RedissonClient redissonClient;

    /**
     * 每5分钟执行一次点赞数据同步
     * 将Redis中的点赞数据同步到MySQL
     */
    @Scheduled(cron = "0 */5 * * * ?")
    public void syncCommentThumbToDb() {
        // 获取分布式锁，防止多节点重复执行
        RLock lock = redissonClient.getLock("comment:thumb:sync:lock");
        try {
            // 尝试获取锁，最多等待10秒，锁有效期60秒
            if (lock.tryLock(10, 60, TimeUnit.SECONDS)) {
                log.info("开始同步评论点赞数据到MySQL");

                try {
                    // 1. 获取所有需要同步的评论ID
                    Set<String> commentIds = commentThumbRedisService.getCommentIdsNeedSync();
                    if (CollUtil.isEmpty(commentIds)) {
                        log.info("没有需要同步的评论点赞数据");
                        return;
                    }

                    log.info("需要同步的评论数量：{}，评论ID：{}", commentIds.size(), commentIds);

                    // 2. 遍历每个评论进行同步
                    for (String commentIdStr : commentIds) {
                        Long commentId = Long.parseLong(commentIdStr);
                        try {
                            syncSingleCommentThumb(commentId);
                        } catch (Exception e) {
                            log.error("同步评论点赞数据失败，评论ID：{}，错误：", commentId, e);
                        }
                    }

                    // 3. 清空已同步的评论ID集合
                    redisTemplate.delete("comment:thumb:sync:set");

                    log.info("评论点赞数据同步完成");
                } catch (Exception e) {
                    log.error("同步评论点赞数据异常：", e);
                }
            } else {
                log.info("未获取到同步锁，跳过本次同步任务");
            }
        } catch (InterruptedException e) {
            log.error("获取同步锁被中断：", e);
            Thread.currentThread().interrupt();
        } finally {
            // 释放锁
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 同步单个评论的点赞数据
     */
    private void syncSingleCommentThumb(Long commentId) {
        log.info("开始同步评论点赞数据，评论ID：{}，时间：{}", commentId, java.time.LocalDateTime.now());

        // 1. 获取Redis中的点赞用户列表
        Set<String> likedUserIds = commentThumbRedisService.getCommentLikedUsers(commentId);

        // 2. 获取数据库中的点赞用户列表
        QueryWrapper<QuestionCommentThumb> dbQueryWrapper = new QueryWrapper<>();
        dbQueryWrapper.eq("commentId", commentId);
        List<QuestionCommentThumb> dbThumbs = questionCommentThumbMapper.selectList(dbQueryWrapper);
        Set<Long> dbUserIds = dbThumbs.stream()
                .map(QuestionCommentThumb::getUserId)
                .collect(Collectors.toSet());

        // 3. 计算需要新增和删除的点赞记录
        Set<Long> redisUserIds = likedUserIds.stream()
                .map(Long::parseLong)
                .collect(Collectors.toSet());

        // 需要新增的点赞记录（在Redis中存在，但在数据库中不存在）
        List<QuestionCommentThumb> thumbsToAdd = new ArrayList<>();
        for (Long userId : redisUserIds) {
            if (!dbUserIds.contains(userId)) {
                QuestionCommentThumb thumb = new QuestionCommentThumb();
                thumb.setCommentId(commentId);
                thumb.setUserId(userId);
                thumb.setCreateTime(new java.util.Date());
                thumb.setUpdateTime(new java.util.Date());
                thumbsToAdd.add(thumb);
            }
        }

        // 需要删除的点赞记录（在数据库中存在，但在Redis中不存在）
        List<Long> thumbIdsToDelete = new ArrayList<>();
        for (QuestionCommentThumb dbThumb : dbThumbs) {
            if (!redisUserIds.contains(dbThumb.getUserId())) {
                thumbIdsToDelete.add(dbThumb.getId());
            }
        }

        // 4. 批量新增点赞记录
        if (CollUtil.isNotEmpty(thumbsToAdd)) {
            for (QuestionCommentThumb thumb : thumbsToAdd) {
                questionCommentThumbMapper.insert(thumb);
            }
            log.info("新增点赞记录数量：{}，评论ID：{}", thumbsToAdd.size(), commentId);
        }

        // 5. 批量删除点赞记录
        if (CollUtil.isNotEmpty(thumbIdsToDelete)) {
            questionCommentThumbMapper.deleteBatchIds(thumbIdsToDelete);
            log.info("删除点赞记录数量：{}，评论ID：{}", thumbIdsToDelete.size(), commentId);
        }

        // 6. 更新评论的点赞数量
        int newThumbNum = likedUserIds.size();
        QuestionComment comment = new QuestionComment();
        comment.setId(commentId);
        comment.setThumbNum(newThumbNum);
        comment.setUpdateTime(new java.util.Date());
        questionCommentMapper.updateById(comment);

        log.info("同步评论点赞数据完成，评论ID：{}，点赞数量：{}", commentId, newThumbNum);
    }
}